﻿using System;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Controls;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;

namespace DXTools.Core
{

    public static class DataGridExtensions
    {
        public static void Export(this DataGrid dg)
        {
            ExportDataGrid(dg);
        }

        /// <summary>
        /// Export single grid of data
        /// </summary>
        /// <param name="dGrid"></param>
        public static void ExportDataGrid(DataGrid dGrid)
        {
            SaveFileDialog objSFD = new SaveFileDialog() { DefaultExt = "csv", Filter = "CSV Files (*.csv)|*.csv|Excel XML (*.xml)|*.xml|All files (*.*)|*.*", FilterIndex = 1 };
            
            if (objSFD.ShowDialog() == true)
            {
                string strFormat = objSFD.SafeFileName.Substring(objSFD.SafeFileName.IndexOf('.') + 1).ToUpper();
                StringBuilder strBuilder = new StringBuilder();
                if (dGrid.ItemsSource == null) return;
                List<string> lstFields = new List<string>();
                if (dGrid.HeadersVisibility == DataGridHeadersVisibility.Column || dGrid.HeadersVisibility == DataGridHeadersVisibility.All)
                {
                    foreach (DataGridColumn dgcol in dGrid.Columns)
                    {
                        if (dgcol is DataGridBoundColumn)
                        {
                            lstFields.Add(FormatField(dgcol.Header.ToString(), strFormat));
                        }
                    }
                    BuildStringOfRow(strBuilder, lstFields, strFormat);
                }
                foreach (object data in dGrid.ItemsSource)
                {
                    lstFields.Clear();
                    foreach (DataGridColumn col in dGrid.Columns)
                    {
                        object strValue = null;
                        Binding objBinding = null;
                        if (col is DataGridBoundColumn)
                        {
                            objBinding = (col as DataGridBoundColumn).Binding;

                            if (objBinding != null)
                            {
                                if (objBinding.Path.Path != "")
                                {
                                    PropertyInfo pi = data.GetType().GetProperty(objBinding.Path.Path);

                                    if (pi != null)
                                    {
                                        if (pi.GetValue(data, null) != null)
                                        {
                                            strValue = pi.GetValue(data, null);
                                        }
                                        else
                                        {
                                            strValue = null;
                                        }
                                    }

                                }
                                if (objBinding.Converter != null)
                                {
                                    if (strValue != null)
                                        strValue = objBinding.Converter.Convert(strValue, typeof(string), objBinding.ConverterParameter, objBinding.ConverterCulture).ToString();
                                    //else
                                    //{

                                    //    strValue = objBinding.Converter.Convert(data, typeof(string),  objBinding.Path.Path, objBinding.ConverterCulture).ToString();
                                    //}
                                }
                            }
                            lstFields.Add(FormatField((strValue != null) ? strValue.ToString() : "", strFormat));
                        }

                    }
                    BuildStringOfRow(strBuilder, lstFields, strFormat);
                }
                StreamWriter sw = new StreamWriter(objSFD.OpenFile());
                if (strFormat == "XML")
                {
                    //Let us write the headers for the Excel XML
                    WriteExcelXmlHeader(sw);
                    sw.WriteLine("<Worksheet ss:Name=\"Export\" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\">");
                    sw.WriteLine("<Table>");
                }
                sw.Write(strBuilder.ToString());
                if (strFormat == "XML")
                {
                    sw.WriteLine("</Table>");
                    sw.WriteLine("</Worksheet>");
                    WriteExcelXmlFooter(sw);
                }
                sw.Close();
            }
        }


        public static void ExportDataGrids(ICollection<DataGridExportSheet> grids, Stream stream, String strFormat)
        {

                using (StreamWriter sw = new StreamWriter(stream))
                {
                    WriteExcelXmlHeader(sw);

                    foreach (var dGrid in grids)
                    {

                        StringBuilder strBuilder = new StringBuilder();
                        if (dGrid.Grid.ItemsSource != null)
                        {
                            List<string> lstFields = new List<string>();
                            if (dGrid.Grid.HeadersVisibility == DataGridHeadersVisibility.Column || dGrid.Grid.HeadersVisibility == DataGridHeadersVisibility.All)
                            {
                                foreach (DataGridColumn dgcol in dGrid.Grid.Columns)
                                {
                                    if (dgcol is DataGridBoundColumn)
                                    {
                                        lstFields.Add(FormatField(dgcol.Header.ToString(), strFormat));
                                    }
                                }
                                BuildStringOfRow(strBuilder, lstFields, strFormat);
                            }
                            foreach (object data in dGrid.Grid.ItemsSource)
                            {
                                lstFields.Clear();
                                foreach (DataGridColumn col in dGrid.Grid.Columns)
                                {
                                    object strValue = null;
                                    Binding objBinding = null;
                                    if (col is DataGridBoundColumn)
                                    {
                                        objBinding = (col as DataGridBoundColumn).Binding;

                                        if (objBinding != null)
                                        {
                                            if (objBinding.Path.Path != "")
                                            {
                                                PropertyInfo pi = data.GetType().GetProperty(objBinding.Path.Path);

                                                if (pi != null)
                                                {
                                                    if (pi.GetValue(data, null) != null)
                                                    {
                                                        strValue = pi.GetValue(data, null);
                                                    }
                                                    else
                                                    {
                                                        strValue = null;
                                                    }
                                                }

                                            }
                                            if (objBinding.Converter != null)
                                            {
                                                if (strValue != null)
                                                    strValue = objBinding.Converter.Convert(strValue, typeof(string), objBinding.ConverterParameter, objBinding.ConverterCulture).ToString();

                                            }
                                        }
                                        lstFields.Add(FormatField((strValue != null) ? strValue.ToString() : "", strFormat));
                                    }

                                }
                                BuildStringOfRow(strBuilder, lstFields, strFormat);
                            }


                            sw.WriteLine("<Worksheet ss:Name=\"" + dGrid.Name + "\" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\">");
                            sw.WriteLine("<Table>");

                            sw.Write(strBuilder.ToString());

                            sw.WriteLine("</Table>");
                            sw.WriteLine("</Worksheet>");

                        }
                    }

                    WriteExcelXmlFooter(sw);
                    sw.Close();
                }
            
            
            
        }



        private static void BuildStringOfRow(StringBuilder strBuilder, List<string> lstFields, string strFormat)
        {
            switch (strFormat)
            {
                case "XML":
                    strBuilder.AppendLine("<Row>");
                    strBuilder.AppendLine(String.Join("\r\n", lstFields.ToArray()));
                    strBuilder.AppendLine("</Row>");
                    break;
                case "CSV":
                    strBuilder.AppendLine(String.Join(",", lstFields.ToArray()));
                    break;
            }
        }
        private static string FormatField(string data, string format)
        {
            switch (format)
            {
                case "XML":
                    return String.Format("<Cell><Data ss:Type=\"String\">{0}</Data></Cell>", data);
                case "CSV":
                    return String.Format("\"{0}\"", data.Replace("\"", "\"\"\"").Replace("\n", "").Replace("\r", ""));
            }
            return data;
        }

        private static void WriteExcelXmlHeader(StreamWriter stream)
        {
            //Let us write the headers for the Excel XML
            stream.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
            stream.WriteLine("<?mso-application progid=\"Excel.Sheet\"?>");
            stream.WriteLine("<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\">");
            stream.WriteLine("<DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\">");
            stream.WriteLine("<Author></Author>");
            stream.WriteLine("<Created>" + DateTime.Now.ToLocalTime().ToLongDateString() + "</Created>");
            stream.WriteLine("<LastSaved>" + DateTime.Now.ToLocalTime().ToLongDateString() + "</LastSaved>");
            stream.WriteLine("<Company>Dynamics XRM Tools</Company>");
            stream.WriteLine("<Version>12.00</Version>");
            stream.WriteLine("</DocumentProperties>");
        }

        private static void WriteExcelXmlFooter(StreamWriter stream)
        {
            stream.WriteLine("</Workbook>");
        }





    }


    public class DataGridExportSheet
    {
        public DataGrid Grid { get; set; }
        public String Name { get; set; }
    }
}